#pragma once

#include <iostream>
#include <windows.h>
#include "defines.h"
#include "PenteVector.h"
#include "screen.h"
using namespace std;

class PenteBoardNode
{
private:

	/* 8 directional ptr node star
			   7 0 1
				\|/
			  6 -+- 2
				/|\
			   5 4 3
	*///--------------------------------
	PenteBoardNode* directionalNodes[8];
	//----------------------------------

	/* Quadrant management 
	  ptr   ptr   ptr
		\    |    /
		 +---+---+
		 | 3 | 0 |
   ptr --+---+---+-- ptr
		 | 2 | 1 |
		 +---+---+
		/    |    \
	  ptr   ptr   ptr
	  
	**********
	** NOTE **: each quadrant has three pointers that it manages
	**********
	*/

	// if a piece is occupying this node
	bool pieceSet;
	// who owns this node
	int ownedBy;
	// what color if owned
	WORD color;
	// if the cursor is on this location
	bool cursorOn;
	// logical ordering of nodes on the board
	PenteVector logicalPos; // position in terms of nodes on the board
	//starting print position in screen coordinates
	PenteVector printPos;  // pass these to the print function, one for each active quadrant
	
	//holds the actual characters that represent the board game
	unsigned char tiles[NODE_ROW][NODE_COL];

public:
	PenteBoardNode( int a_x, int a_y ) : ownedBy( -1 ), pieceSet( false ), cursorOn( false )
	{ 
		logicalPos.setXY( a_x, a_y );

		//	Useful Character #'s
		//--------------------------------------
		//  blank square filler = 254
		//	Hyphen = 45
		//	Pipes = 124
		//	cursor = 11 
		//	snowflake = 15
		//	node = 4 // diamonds
		//  piece marker = 1 (empty), 2(filled)
		//--------------------------------------
		tiles[0][0] = FILL_SQUARE;	// fill blocks
		tiles[0][1] = FILL_SQUARE;
		tiles[0][2] = VERT_LINE;	// vertical lines
		tiles[0][3] = FILL_SQUARE;
		tiles[0][4] = FILL_SQUARE;
		tiles[1][0] = HORZ_LINE;	// horizontal lines
		tiles[1][1] = HORZ_LINE;
		tiles[1][2] = NODE_CHAR;	// node marker
		tiles[1][3] = HORZ_LINE;
		tiles[1][4] = HORZ_LINE;
		tiles[2][0] = FILL_SQUARE;
		tiles[2][1] = FILL_SQUARE;
		tiles[2][2] = VERT_LINE;
		tiles[2][3] = FILL_SQUARE;
		tiles[2][4] = FILL_SQUARE;
	}
	~PenteBoardNode(){}

	PenteBoardNode& operator=( PenteBoardNode& q)
	{
		for( int i = 0; i < 8; i++ )
		{
			directionalNodes[i] = q.getDirectionalNodes(i);
		}
		pieceSet = q.pieceOnThisNode();
		cursorOn = q.cursorOnThisNode();
	}

	void initializeBoardNode()
	{
		//	Useful Character #'s
		//--------------------------------------
		//  blank square filler = 219
		//	Hyphen = 45
		//	Pipes = 124
		//	cursor = 11 
		//	snowflake = 15
		//	node = 4 // diamonds
		//  piece marker = 1 (empty), 2(filled)
		//--------------------------------------

		//initialize all arrays
		for( int i = 0; i < 8; i++ )
		{
			directionalNodes[i] = NULL;
		}

		printPos.setXY( logicalPos.getY() * NODE_COL + BOARD_X, logicalPos.getX() * NODE_ROW + BOARD_Y );
		
	}

	bool hasNeighbor( int direction ) {	return ( direction < NUM_DIRECTIONS && direction >= 0 && directionalNodes[direction] != NULL ); }

	PenteBoardNode* getDirectionalNodes( int x )
	{ 
		if( x >= 0 && x <= 7 )
			return directionalNodes[x]; 
		else
			return NULL;
	}
	void setDirectionalNodes( int q, PenteBoardNode* p )
	{
		if( q >= 0 && q < NUM_DIRECTIONS )
			directionalNodes[q] = p; 
	}


	bool pieceOnThisNode(){ return pieceSet; } //much simpler -Kaero
	void setPieceOnThisNode( int whichPlayer ){ pieceSet = true; } //oops, didn't see this function... see captureNode()

	bool cursorOnThisNode(){  return cursorOn; } //much simpler -Kaero
	void setCursorOn(){ cursorOn = true; }
	void setCursorOff(){ cursorOn = false; }

	bool captureNode( int player ) {
		if( !pieceOnThisNode() ) {
			ownedBy = player;
			pieceSet = true;
			return true;
		} else {
			return false;
		}
	}

	int getOwner() { return ownedBy; }

	bool changeOwner( int player ) {
		if( ownedBy != player ) {
			if( pieceSet ) {
				ownedBy = player;
			} else {
				return false;
			}
		} else {
			return false;
		}
		return true;
	}

	bool removePiece( int player ) {
		if( ownedBy != player ) {
			if( pieceSet ) {
				ownedBy = player;
				pieceSet = false;
			} else {
				return false;
			}
		} else {
			return false;
		}
		return true;
	}

	void setXY( int a_x, int a_y ){ logicalPos.setXY( a_x, a_y ); }
	PenteVector* getPos(){ return &logicalPos; }

	int getCenterX() { return printPos.getX() + NODE_COL / 2; }
	int getCenterY() { return printPos.getY() + NODE_ROW / 2; }

	void updateBoardNode()
	{
		/*  Standard Node Tile initialization

			tiles[0][0] = 254;	// fill blocks
			tiles[0][1] = 254;
			tiles[0][2] = 124;	// vertical lines
			tiles[0][3] = 254;
			tiles[0][4] = 254;
			tiles[1][0] = 45;	// horizontal lines
			tiles[1][1] = 45;
			tiles[1][2] = 4;	// node marker
			tiles[1][3] = 45;
			tiles[1][4] = 45;
			tiles[2][0] = 254;
			tiles[2][1] = 254;
			tiles[2][2] = 124;
			tiles[2][3] = 254;
			tiles[2][4] = 254;
		*/

		if(cursorOn || pieceSet )
		{
			if(cursorOn)
			{
				//turn on the cursor
				tiles[1][2] = CURSOR;
			}
			else if( pieceSet ) 
			{
				if( ownedBy == PLAYER_ONE ) { // whichPlayer == true  = player 1
					color = PLAYER_ONE_COLOR;
					tiles[1][2] = PLAYER_1;
				} else if( ownedBy == PLAYER_TWO ) {		// whichPlayer == false = player 2
					color = PLAYER_TWO_COLOR;
					tiles[1][2] = PLAYER_2;
				}
			}
		}
		else
		{
			tiles[1][2] = NODE_CHAR;
		}

		if( directionalNodes[NORTH] == NULL )
		{
			tiles[0][0] = FILL_SQUARE;	// fill blocks
			tiles[0][1] = FILL_SQUARE;
			tiles[0][2] = FILL_SQUARE;	// vertical lines
			tiles[0][3] = FILL_SQUARE;
			tiles[0][4] = FILL_SQUARE;
		}
		if( directionalNodes[EAST] == NULL )
		{
			tiles[0][3] = FILL_SQUARE;
			tiles[0][4] = FILL_SQUARE;
			tiles[1][3] = FILL_SQUARE;
			tiles[1][4] = FILL_SQUARE;
			tiles[2][3] = FILL_SQUARE;
			tiles[2][4] = FILL_SQUARE;
		}
		if( directionalNodes[SOUTH] == NULL )
		{
			tiles[2][0] = FILL_SQUARE;
			tiles[2][1] = FILL_SQUARE;
			tiles[2][2] = FILL_SQUARE;
			tiles[2][3] = FILL_SQUARE;
			tiles[2][4] = FILL_SQUARE;
		}
		if( directionalNodes[WEST] == NULL )
		{
			tiles[0][0] = FILL_SQUARE;	// fill blocks
			tiles[0][1] = FILL_SQUARE;
			tiles[1][0] = FILL_SQUARE;	// horizontal lines
			tiles[1][1] = FILL_SQUARE;
			tiles[2][0] = FILL_SQUARE;
			tiles[2][1] = FILL_SQUARE;
		}
	}


	void printBoardNode( Screen *disp )
	{
		//	Useful Character #'s
		//--------------------------------------
		//  blank square filler = 254
		//	Hyphen = 45
		//	Pipes = 124
		//	cursor = 11 
		//	snowflake = 15
		//	node = 4 // diamonds
		//  piece marker = 1 (empty), 2(filled)
		//--------------------------------------
	
		updateBoardNode();

		COORD pos;
	//	SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE), pos );

		for( int row = 0; row < NODE_ROW; ++row ) {
			pos.Y = (short)printPos.getY() + row;
			for( int col = 0; col < NODE_COL; ++col ) {
				pos.X = (short)printPos.getX() + col;
				disp->setAt( pos.X, pos.Y, tiles[row][col], ( tiles[row][col] == FILL_SQUARE ? ( pieceSet ? makeColor( getColorFore( color ), getColorBG( BOARD_COLOR_BLOCK ) ) : BOARD_COLOR_BLOCK ) : ( pieceSet ? makeColor( getColorFore( color ), getColorBG( BOARD_COLOR_SPACE ) ) : BOARD_COLOR_SPACE ) ) );
			}
		}

	/*	for( int col = 0; col < NODE_COL; col++ )
		{
			//cout << tiles[row][col];
			disp->setAt( pos.X, pos.Y, tiles[0][col] );
	//		cout << tiles[0][col];
		}
		
		pos.X = (short)printPos.getY();
		pos.Y = (short)printPos.getX()+1;
	//	SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE), pos );
		
		for( int col = 0; col < NODE_COL; col++ )
		{
			//cout << tiles[row][col];
			//cout << tiles[1][col];
			disp->setAt( pos.X, pos.Y, tiles[1][col] );

		}
		
		pos.X = (short)printPos.getY();
		pos.Y = (short)printPos.getX()+2;
	//	SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE), pos );
		
		for( int col = 0; col < NODE_COL; col++ )
		{
			//cout << tiles[row][col];
	//		cout << tiles[2][col];
			disp->setAt( pos.Y, pos.X, tiles[2][col] );
		}*/
	}

};